﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using SlimDX.Direct3D10;
using SlimDX;
using SlimDX.DXGI;

namespace System.Windows.Media.Media3D10
{
    /// <summary>
    /// Représente une texture d'environnement
    /// </summary>
    public sealed class CubeMap : Animatable
    {
        #region Dependency Properties
        /// <summary>
        /// Identifie la propriété de dépendance <see cref="TopBrush"/>.
        /// </summary>
        public static readonly DependencyProperty TopBrushProperty =
            DependencyProperty.Register("TopBrush", typeof(Brush), typeof(CubeMap));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="BottomBrush"/>.
        /// </summary>
        public static readonly DependencyProperty BottomBrushProperty =
            DependencyProperty.Register("BottomBrush", typeof(Brush), typeof(CubeMap));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="FrontBrush"/>.
        /// </summary>
        public static readonly DependencyProperty FrontBrushProperty =
            DependencyProperty.Register("FrontBrush", typeof(Brush), typeof(CubeMap));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="BackBrush"/>.
        /// </summary>
        public static readonly DependencyProperty BackBrushProperty =
            DependencyProperty.Register("BackBrush", typeof(Brush), typeof(CubeMap));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="LeftBrush"/>.
        /// </summary>
        public static readonly DependencyProperty LeftBrushProperty =
            DependencyProperty.Register("LeftBrush", typeof(Brush), typeof(CubeMap));

        /// <summary>
        /// Identifie la propriété de dépendance <see cref="RightBrush"/>.
        /// </summary>
        public static readonly DependencyProperty RightBrushProperty =
            DependencyProperty.Register("RightBrush", typeof(Brush), typeof(CubeMap));
        #endregion

        #region Public Properties
        /// <summary>
        /// Face supérieur de la texture
        /// </summary>
        public Brush TopBrush
        {
            get { return (Brush)GetValue(TopBrushProperty); }
            set { SetValue(TopBrushProperty, value); }
        }

        /// <summary>
        /// Face inférieure de la texture
        /// </summary>
        public Brush BottomBrush
        {
            get { return (Brush)GetValue(BottomBrushProperty); }
            set { SetValue(BottomBrushProperty, value); }
        }

        /// <summary>
        /// Face avant de la texture
        /// </summary>
        public Brush FrontBrush
        {
            get { return (Brush)GetValue(FrontBrushProperty); }
            set { SetValue(FrontBrushProperty, value); }
        }

        /// <summary>
        /// Face arrière de la texture
        /// </summary>
        public Brush BackBrush
        {
            get { return (Brush)GetValue(BackBrushProperty); }
            set { SetValue(BackBrushProperty, value); }
        }

        /// <summary>
        /// Face gauche de la texture
        /// </summary>
        public Brush LeftBrush
        {
            get { return (Brush)GetValue(LeftBrushProperty); }
            set { SetValue(LeftBrushProperty, value); }
        }

        /// <summary>
        /// Face droite de la texture
        /// </summary>
        public Brush RightBrush
        {
            get { return (Brush)GetValue(RightBrushProperty); }
            set { SetValue(RightBrushProperty, value); }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Converti le <see cref="CubeMap"/> et <see cref="Texture2D"/>
        /// </summary>
        /// <returns><see cref="CubeMap"/> converti.</returns>
        public Texture2D ToTextureCube()
        { 
            Texture2D topTexture = null;
            Texture2D bottomTexture = null;
            Texture2D frontTexture = null;
            Texture2D backTexture = null;
            Texture2D leftTexture = null;
            Texture2D rightTexture = null;
            Texture2D textureCube = null;
            DataRectangle[] data = new DataRectangle[6];

            try
            {
                topTexture = TopBrush.ToTexture2D();
                bottomTexture = TopBrush.ToTexture2D();
                frontTexture = TopBrush.ToTexture2D();
                backTexture = TopBrush.ToTexture2D();
                leftTexture = TopBrush.ToTexture2D();
                rightTexture = TopBrush.ToTexture2D();
                
                Texture2DDescription description = new Texture2DDescription();
                description.ArraySize = 6;
                description.BindFlags = BindFlags.ShaderResource;
                description.CpuAccessFlags = CpuAccessFlags.None;
                description.OptionFlags = ResourceOptionFlags.TextureCube;
                description.SampleDescription = new SampleDescription(1, 0);
                description.Usage = ResourceUsage.Default;

                Engine.Device10.ResolveSubresource(topTexture, 0, textureCube, 0, Format.B8G8R8A8_UNorm);
            }
            finally
            {
                if (topTexture != null)
                {
                    topTexture.Dispose();
                    topTexture = null;
                }
                if (bottomTexture != null)
                {
                    bottomTexture.Dispose();
                    bottomTexture = null;
                }
                if (frontTexture != null)
                {
                    frontTexture.Dispose();
                    frontTexture = null;
                }
                if (backTexture != null)
                {
                    backTexture.Dispose();
                    backTexture = null;
                }
                if (leftTexture != null)
                {
                    leftTexture.Dispose();
                    leftTexture = null;
                }
                if (rightTexture != null)
                {
                    rightTexture.Dispose();
                    rightTexture = null;
                }
            }

            return textureCube;
        }
        #endregion

        #region Freezable Implementation
        /// <summary>
        /// Une fois implémentée dans une classe dérivée, initialise une nouvelle instance de la classe dérivée <see cref="Freezable"/>. 
        /// </summary>
        /// <returns>Nouvelle instance.</returns>
        protected override Freezable CreateInstanceCore()
        {
            return new SkyboxModel3D10();
        }
        #endregion
    }
}
